﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using DataTier;
using ElectricCar.ElectricCarService;
using System.Threading;
using System.Threading.Tasks;

namespace ElectricCar
{
    public partial class MainForm : Form
    {

        private IElectricCarService _serviceClient = new ElectricCarServiceClient();

        private Task _updateLocationsTask = null;
        private Task _updateReservationsTask = null;
        private Task _updateRouteTask = null;
        private Customer _customer;

        public MainForm()
        {
            InitializeComponent();
        }

        private void MainForm_Load(object sender, EventArgs e)
        {
            DisableCustomerUI();
            UpdateLocations();
        }

        private void EnableCustomerUI()
        {
            tabControl1.SelectedTab = tabFindRoute;
            ((Control)tabFindRoute).Enabled = true;
            ((Control)tabReservations).Enabled = true;
            ((Control)tabLogin).Enabled = false;
        }

        private void DisableCustomerUI()
        {
            ((Control)tabFindRoute).Enabled = false;
            ((Control)tabReservations).Enabled = false;
        }

        private void UpdateLocations()
        {
            if (_updateLocationsTask == null)
            {

                _updateLocationsTask = new Task(() =>
                {

                    IList<Location> fromLocations = _serviceClient.GetAllLocations();
                    IList<Location> toLocations = _serviceClient.GetAllLocations();

                    _updateLocationsTask = null;

                    this.Invoke(new Action(() =>
                    {
                        cmbFromLocation.DataSource = fromLocations;
                        cmbToLocation.DataSource = toLocations;

                    }));

                });

                _updateLocationsTask.Start();

            }
        }

        private void UpdateReservations()
        {

            if (_updateReservationsTask == null)
            {

                _updateReservationsTask = new Task(() =>
                {

                    IList<Reservation> reservations = _serviceClient.GetReservations(_customer);

                    _updateReservationsTask = null;

                    this.Invoke(new Action(() =>
                    {
                        lstReservations.DataSource = reservations;
                    }));

                });

                _updateReservationsTask.Start();

            }

        }

        private void UpdateRoute(Location from, Location to)
        {

            btnFindRoute.Enabled = false;

            if (_updateRouteTask == null)
            {

                _updateRouteTask = new Task(() =>
                {

                    Route route = _serviceClient.FindPath(from, to);
                    _serviceClient.AddReservation(_customer, route);

                    _updateRouteTask = null;

                    this.Invoke(new Action(() =>
                    {

                        btnFindRoute.Enabled = true;
                        lstRouteDescription.DataSource = route.GetDescription();

                        UpdateReservations();

                        MessageBox.Show("Route found. Please check your reservations");

                    }));

                });

                _updateRouteTask.Start();

            }

        }

        private void btnFindRoute_Click(object sender, EventArgs e)
        {

            try
            {
                UpdateRoute((Location)cmbFromLocation.SelectedItem, (Location)cmbToLocation.SelectedItem);
            }
            catch (Exception ex)
            {
                MessageBox.Show("Could not find route. Error: " + ex.ToString());
            }

        }

        private void btnLogin_Click(object sender, EventArgs e)
        {

            try
            {

                _customer = _serviceClient.Login(Convert.ToInt32(txtUsername.Text), txtPassword.Text);

                if (_customer != null)
                {
                    MessageBox.Show(_customer.ToString() + " logged in");
                    EnableCustomerUI();
                    UpdateReservations();
                }
                else
                {
                    MessageBox.Show("Invalid username/password");
                }

            }
            catch (Exception ex)
            {
                MessageBox.Show("Could not log in. Error: " + ex.ToString());
            }

        }

        private void lstReservations_SelectedIndexChanged(object sender, EventArgs e)
        {
            Reservation selectedReservation = (Reservation)lstReservations.SelectedItem;
            lstPartReservations.DataSource = selectedReservation.PartReservations;
        }

        private void lstPartReservations_SelectedIndexChanged(object sender, EventArgs e)
        {

            PartReservation selectedPartReservation = (PartReservation)lstPartReservations.SelectedItem;

            if (selectedPartReservation != null)
            {
                txtExpirationDate.Text = selectedPartReservation.ExpirationDate.ToString();
                txtPickUpDate.Text = selectedPartReservation.PickUpDate.ToString();
            }

        }

        private void btnRemoveReservation_Click(object sender, EventArgs e)
        {

            if (lstReservations.SelectedItem != null)
            {

                try
                {

                    Reservation selectedReservation = (Reservation)lstReservations.SelectedItem;
                    _serviceClient.RemoveReservation(selectedReservation);

                    UpdateReservations();

                    lstPartReservations.DataSource = null;
                    txtPickUpDate.Clear();
                    txtExpirationDate.Clear();

                }
                catch (Exception ex)
                {
                    MessageBox.Show("Could not remove reservation. Error: " + ex.ToString());
                }

            }

        }

    }
}
